home *** CD-ROM | disk | FTP | other *** search
/ Skunkware 5 / Skunkware 5.iso / src / Tools / lynx-2.4 / WWW / Library / Implementation / HTPasswd.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-06-28  |  7.6 KB  |  302 lines

  1.  
  2. /* MODULE                            HTPasswd.c
  3. **        PASSWORD FILE ROUTINES
  4. **
  5. ** AUTHORS:
  6. **    AL    Ari Luotonen    luotonen@dxcern.cern.ch
  7. **    MD    Mark Donszelmann    duns@vxdeop.cern.ch
  8. **
  9. ** HISTORY:
  10. **     7 Nov 93     MD     free for crypt taken out (static data returned) 
  11. **
  12. **
  13. ** BUGS:
  14. **
  15. **
  16. */
  17.  
  18.  
  19. #include "HTUtils.h"
  20. #include "tcp.h"    /* FROMASCII()        */
  21. #include <string.h>
  22. #include "HTAAUtil.h"    /* Common parts of AA    */
  23. #include "HTAAFile.h"    /* File routines    */
  24. #include "HTPasswd.h"    /* Implemented here    */
  25.  
  26. #include "LYLeaks.h"
  27.  
  28. extern char *crypt();
  29.  
  30.  
  31. PRIVATE char salt_chars [65] =
  32.     "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789./";
  33.  
  34.  
  35. /* PRIVATE                        next_rec()
  36. **        GO TO THE BEGINNING OF THE NEXT RECORD
  37. **        Otherwise like HTAAFile_nextRec() but
  38. **        does not handle continuation lines
  39. **        (because password file has none).
  40. ** ON ENTRY:
  41. **    fp    is the password file from which records are read from.
  42. **
  43. ** ON EXIT:
  44. **    returns    nothing. File read pointer is located at the beginning
  45. **        of the next record.
  46. */
  47. PRIVATE void next_rec ARGS1(FILE *, fp)
  48. {
  49.     int ch = getc(fp);
  50.  
  51.     while (ch != EOF  &&  ch != CR  &&  ch != LF)
  52.     ch = getc(fp);        /* Skip until end-of-line */
  53.  
  54.     while (ch != EOF &&
  55.        (ch == CR  ||  ch == LF))    /*Skip carriage returns and linefeeds*/
  56.     ch = getc(fp);
  57.  
  58.     if (ch != EOF)
  59.     ungetc(ch, fp);
  60. }
  61.  
  62.  
  63. /* PUBLIC                        HTAA_encryptPasswd()
  64. **        ENCRYPT PASSWORD TO THE FORM THAT IT IS SAVED
  65. **        IN THE PASSWORD FILE.
  66. ** ON ENTRY:
  67. **    password    is a string of arbitrary lenght.
  68. **
  69. ** ON EXIT:
  70. **    returns        password in one-way encrypted form.
  71. **
  72. ** NOTE:
  73. **    Uses currently the C library function crypt(), which
  74. **    only accepts at most 8 characters long strings and produces
  75. **    always 13 characters long strings. This function is
  76. **    called repeatedly so that longer strings can be encrypted.
  77. **    This is of course not as safe as encrypting the entire
  78. **    string at once, but then again, we are not that paranoid
  79. **    about the security inside the machine.
  80. **
  81. */
  82. PUBLIC char *HTAA_encryptPasswd ARGS1(CONST char *, password)
  83. {
  84.     char salt[3];
  85.     char chunk[9];
  86.     char *result;
  87.     char *tmp;
  88.     CONST char *cur = password;
  89.     int len = strlen(password);
  90.     extern time_t theTime;
  91.     int random = (int)theTime;    /* This is random enough */
  92.  
  93.     if (!(result = (char*)malloc(13*((strlen(password)+7)/8) + 1)))
  94.     outofmem(__FILE__, "HTAA_encryptPasswd");
  95.  
  96.     *result = (char)0;
  97.     while (len > 0) {
  98.     salt[0] = salt_chars[random%64];
  99.     salt[1] = salt_chars[(random/64)%64];
  100.     salt[2] = (char)0;
  101.  
  102.     strncpy(chunk, cur, 8);
  103.     chunk[8] = (char)0;
  104.  
  105.     tmp = crypt((char*)password, salt);  /*crypt() doesn't change its args*/
  106.     strcat(result, tmp);
  107.  
  108.     cur += 8;
  109.     len -= 8;
  110.     } /* while */
  111.  
  112.     return result;
  113. }
  114.  
  115.  
  116.  
  117. /* PUBLIC                        HTAA_passwdMatch()
  118. **        VERIFY THE CORRECTNESS OF A GIVEN PASSWORD
  119. **        AGAINST A ONE-WAY ENCRYPTED FORM OF PASSWORD.
  120. ** ON ENTRY:
  121. **    password    is cleartext password.
  122. **    encrypted    is one-way encrypted password, as returned
  123. **            by function HTAA_encryptPasswd().
  124. **            This is typically read from the password
  125. **            file.
  126. **
  127. ** ON EXIT:
  128. **    returns        YES, if password matches the encrypted one.
  129. **            NO, if not, or if either parameter is NULL.
  130. ** FIX:
  131. **    Only the length of original encrypted password is
  132. **    checked -- longer given passwords are accepted if
  133. **    common length is correct (but not shorter).
  134. **    This is to allow interoperation of servers and clients
  135. **    who have a hard-coded limit of 8 to password.
  136. */
  137. PUBLIC BOOL HTAA_passwdMatch ARGS2(CONST char *, password,
  138.                    CONST char *, encrypted)
  139. {
  140.     char *result;
  141.     int len;
  142.     int status;
  143.  
  144.     if (!password || !encrypted)
  145.     return NO;
  146.  
  147.     len = 13*((strlen(password)+7)/8);
  148.     if (len < strlen(encrypted))
  149.     return NO;
  150.  
  151.     if (!(result = (char*)malloc(len + 1)))
  152.     outofmem(__FILE__, "HTAA_encryptPasswd");
  153.  
  154.     *result = (char)0;
  155.     while (len > 0) {
  156.     char salt[3];
  157.     char chunk[9];
  158.     CONST char *cur1 = password;
  159.     CONST char *cur2 = encrypted;
  160.     char *tmp;
  161.  
  162.     salt[0] = *cur2;
  163.     salt[1] = *(cur2+1);
  164.     salt[2] = (char)0;
  165.  
  166.     strncpy(chunk, cur1, 8);
  167.     chunk[8] = (char)0;
  168.  
  169.     tmp = crypt((char*)password, salt);
  170.     strcat(result, tmp);
  171.  
  172.     cur1 += 8;
  173.     cur2 += 13;
  174.     len -= 13;
  175.     } /* while */
  176.  
  177.     status = strncmp(result, encrypted, strlen(encrypted));
  178.  
  179.     if (TRACE)
  180.     fprintf(stderr,
  181.         "%s `%s' (encrypted: `%s') with: `%s' => %s\n",
  182.         "HTAA_passwdMatch: Matching password:",
  183.         password, result, encrypted,
  184.         (status==0 ? "OK" : "INCORRECT"));
  185.  
  186.     free(result);
  187.  
  188.     if (status==0)
  189.     return YES;
  190.     else
  191.     return NO;
  192. }
  193.  
  194.  
  195. /* PUBLIC                    HTAAFile_readPasswdRec()
  196. **            READ A RECORD FROM THE PASSWORD FILE
  197. ** ON ENTRY:
  198. **    fp        open password file
  199. **    out_username    buffer to put the read username, must be at
  200. **            least MAX_USERNAME_LEN+1 characters long.
  201. **    out_passwd    buffer to put the read password, must be at
  202. **            least MAX_PASSWORD_LEN+1 characters long.
  203. ** ON EXIT:
  204. **    returns        EOF on end of file,
  205. **            otherwise the number of read fields
  206. **            (i.e. in a correct case returns 2).
  207. **    out_username    contains the null-terminated read username.
  208. **    out_password    contains the null-terminated read password.
  209. **
  210. ** FORMAT OF PASSWORD FILE:
  211. **    username:password:maybe real name or other stuff
  212. **                (may include even colons)
  213. **
  214. **    There may be whitespace (blanks or tabs) in the beginning and
  215. **    the end of each field. They are ignored.
  216. */
  217. PUBLIC int HTAAFile_readPasswdRec ARGS3(FILE *, fp,
  218.                     char *, out_username,
  219.                     char *, out_password)
  220. {
  221.     char terminator;
  222.     
  223.     terminator = HTAAFile_readField(fp, out_username, MAX_USERNAME_LEN);
  224.  
  225.     if (terminator == EOF) {                /* End of file */
  226.     return EOF;
  227.     }
  228.     else if (terminator == CR  ||  terminator == LF) {    /* End of line */
  229.     next_rec(fp);
  230.     return 1;
  231.     }
  232.     else {
  233.     HTAAFile_readField(fp, out_password, MAX_PASSWORD_LEN);
  234.     next_rec(fp);
  235.     return 2;
  236.     }
  237. }
  238.  
  239.  
  240.  
  241. /* PUBLIC                        HTAA_checkPassword()
  242. **        CHECK A USERNAME-PASSWORD PAIR
  243. ** ON ENTRY:
  244. **    username    is a null-terminated string containing
  245. **            the client's username.
  246. **    password    is a null-terminated string containing
  247. **            the client's corresponding password.
  248. **    filename    is a null-terminated absolute filename
  249. **            for password file.
  250. **            If NULL or empty, the value of
  251. **            PASSWD_FILE is used.
  252. ** ON EXIT:
  253. **    returns        YES, if the username-password pair was correct.
  254. **            NO, otherwise; also, if open fails.
  255. */
  256. PUBLIC BOOL HTAA_checkPassword ARGS3(CONST char *, username,
  257.                      CONST char *, password,
  258.                      CONST char *, filename)
  259. {
  260.     FILE *fp = NULL;
  261.     char user[MAX_USERNAME_LEN+1];
  262.     char pw[MAX_PASSWORD_LEN+1];
  263.     int status;
  264.     
  265.     if (filename && *filename)  fp = fopen(filename,"r");
  266.     else            fp = fopen(PASSWD_FILE,"r");
  267.  
  268.     if (!fp) {
  269.     if (TRACE) fprintf(stderr, "%s `%s'\n",
  270.                "HTAA_checkPassword: Unable to open password file",
  271.                (filename && *filename ? filename : PASSWD_FILE));
  272.     return NO;
  273.     }
  274.     do {
  275.     if (2 == (status = HTAAFile_readPasswdRec(fp,user,pw))) {
  276.         if (TRACE)
  277.         fprintf(stderr,
  278.             "HTAAFile_validateUser: %s \"%s\" %s \"%s:%s\"\n",
  279.             "Matching username:", username,
  280.             "against passwd record:", user, pw);
  281.         if (username  &&  user  &&  !strcmp(username,user)) {
  282.         /* User's record found */
  283.         if (*pw != '\0') { /* So password is required for this user */
  284.             if (!password ||
  285.             !HTAA_passwdMatch(password,pw)) /* Check the password */
  286.             status = EOF;    /* If wrong, indicate it with EOF */
  287.         }
  288.         break;  /* exit loop */
  289.         }  /* if username found */
  290.     }  /* if record is ok */
  291.     } while (status != EOF);
  292.  
  293.     fclose(fp);
  294.     
  295.     if (TRACE) fprintf(stderr, "HTAAFile_checkPassword: (%s,%s) %scorrect\n",
  296.                username, password, ((status != EOF) ? "" : "in"));
  297.  
  298.     if (status == EOF)  return NO;  /* We traversed to the end without luck */
  299.     else                return YES; /* The user was found */
  300. }
  301.  
  302.